#include <sys/types.h>
#include <sys/socket.h>
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdio>

#define SERVER_PORT 6666
#define SERVER_IN  "127.0.0.1"

int main(){
    int lfd, cfd;
    struct sockaddr_in serv_addr, clie_addr;
    socklen_t clie_addr_len, clie_IP_len;
    char buf[BUFSIZ], client_IP[BUFSIZ];
    int n;

    lfd = socket(AF_INET, SOCK_STREAM, 0);//创建一个套接字，用一个文件描述符来接收
    if (lfd == -1){
        perror("socket error");
        exit(1);
    }

    // 定义该服务器的地址结构
    serv_addr.sin_family = AF_INET;//定义ipv4版本
    serv_addr.sin_port = htons(SERVER_PORT);//定义套接字的端口号
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//定义套接字的ip地址

    // 将套接字与地址结构体进行绑定
    if (bind(lfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1){
        perror("bind error");
        exit(1);
    }
    
    // 定义该套接字最大的同时请求数量,并使该套接字成为监听套接字, 即插座中的插销
    if(listen(lfd, 32) == -1){
        perror("listen error");
        exit(1);
    }

    clie_addr_len = sizeof(clie_addr);

    // 阻塞等待服务,从完成队列的队头返回一个给进程, 产生一个已连接套接字, 用于服务器与此客户端进行通讯,
    // 之后的读写操作都是通过此已连接套接字进行
    cfd = accept(lfd, (struct sockaddr*)&clie_addr, &clie_addr_len);
    if (cfd == -1){
        perror("accept error");
        exit(1);
    }
    printf("client IP:%s, client Ip:%d\n", 
            inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, client_IP, sizeof(client_IP)),
            ntohs(clie_addr.sin_port));

    while(1){

        // 从服务器套接字read缓冲区中读取数据到缓存当中
        n = read(cfd, buf, sizeof(buf));

        for (int i = 0;i < n;i++){
            buf[i] = toupper(buf[i]);
        }

        // 
        write(cfd, buf, n);

    }

    // 关闭套接字
    close(lfd);
    close(cfd);

    return 0;
    
}
